/***************************************************************************
 *   Copyright (C) 2008 by Dr Pierre-Marie DESOMBRE                        *
 *   pm.desombre@medsyn.fr                                                 *
 *                  on a idea from Eric Maeker                             *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "connexion.h"
#include "settings.h"
#include "icore.h"
#include "constants.h"
#include "mdp.h"
	
#include <QProgressDialog>
#include <QMessageBox>
#include <QString>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QApplication>
#include <QtSql>
#include <QDebug>
#include <QCursor>
bool WarnDebugMessage;
using namespace Common;
using namespace Constants;

static inline  Settings *settings() {return Common::ICore::instance()->settings(); }

Connexion::Connexion(QObject *parent) :
        QObject(parent),
        m_IsDBConfigured(false)
{}

Connexion::~Connexion()
{}
bool Connexion::connectToDrTux(){
    Q_ASSERT(!settings()->isClean());
    int driverType = 0;
    QString log    = settings()->value(Constants::S_DB_LOGIN).toString();
    QString pass   = settings()->value(Constants::S_DB_PASSWORD).toString();
    QString host   = settings()->value(Constants::S_DB_HOST).toString();
    QString port   = settings()->value(Constants::S_DB_PORT).toString();
    QString driver = settings()->value(Constants::S_DRIVER_DRTUX).toString();
    //--------test driver--------------------------------
    qDebug() << __FILE__ << QString::number(__LINE__)  << "Driver chosen is "+driver;
    if(driver == "MYSQL"){
        driverType = Driver_MySQL;
    }
    else if(driver == "SQLITE"){
        driverType = Driver_SQLite;
    }
    else if(driver == "POSTGRESQL"){
        driverType = Driver_PostGreSQL;
    }
    else{
        QMessageBox::critical(0,trUtf8("Critical"),trUtf8("Le driver de la base de données ne peut pas être défini.\n"
                    "Vous devez écrire dans config.ini après Driver :\n"
                    "pour MySql : MYSQL\npour Sqlite : SQLITE\npour PostGresql : POSTGRESQL."),QMessageBox::Ok);
        return false;
    }
    //--------------------------------------
    QSqlDatabase db;
    bool dbTest = 0;
    switch (driverType) {
        case Driver_MySQL :
        {
            db = QSqlDatabase::addDatabase("QMYSQL", Constants::DB_DRTUX);
            db.setHostName(host);
            db.setDatabaseName(Constants::DB_DRTUX);
            db.setUserName(log);
            db.setPassword(pass);
              if (WarnDebugMessage){
                qWarning() << "Connecting DrTux database" << host << Constants::DB_DRTUX << log << pass << port;
              }
            dbTest = (!db.isOpen()) && (!db.open());
            break;
        }
        case Driver_SQLite :
        {
            db = QSqlDatabase::addDatabase("QSQLITE", Constants::DB_DRTUX);
            db.setDatabaseName(settings()->userResourcesPath() + QDir::separator() + Constants::DB_DRTUX + ".db");
              if (WarnDebugMessage){
                qWarning() << "Connecting DrTux database SQLite " + db.databaseName() +" "+ QString::number(__LINE__);
              }
            if(!db.open()){
                qWarning() << "database drtux cannot open";
            }
            QStringList tables = db.tables();
            qDebug() << "tables "+QString::number(tables.size());
            dbTest = (tables.size() < 1);
            break;
        }
        case Driver_PostGreSQL :
            break;
    }

    if (dbTest) {
        if (WarnDebugMessage){
                qWarning() << "Connected to DrTux database"
                           << db.databaseName()
                           << __FILE__
                           << QString::number(__LINE__);
            }
        else {return false;}
    }
    return true;
}
bool Connexion::connect()
{
    Q_ASSERT(!settings()->isClean());
    int driverType = 0;
    QString log    = settings()->value(Constants::S_DB_LOGIN).toString();
    QString pass   = settings()->value(Constants::S_DB_PASSWORD).toString();
    QString host   = settings()->value(Constants::S_DB_HOST).toString();
    QString port   = settings()->value(Constants::S_DB_PORT).toString();
    QString driver = settings()->value(Constants::S_DRIVER).toString();
    //--------test driver--------------------------------
    qDebug() << __FILE__ << QString::number(__LINE__)  << "Driver chosen is "+driver;
    if(driver == "MYSQL"){
        driverType = Driver_MySQL;
    }
    else if(driver == "SQLITE"){
        driverType = Driver_SQLite;
    }
    else if(driver == "POSTGRESQL"){
        driverType = Driver_PostGreSQL;
    }
    else{
        QMessageBox::critical(0,trUtf8("Critical"),trUtf8("Le driver de la base de données ne peut pas être défini.\n"
                    "Vous devez écrire dans config.ini après Driver :\n"
                    "pour MySql : MYSQL\npour Sqlite : SQLITE\npour PostGresql : POSTGRESQL."),QMessageBox::Ok);
        return false;
    }
    //--------------------------------------
    QSqlDatabase db;
    bool dbTest = 0;
    switch (driverType) {
        case Driver_MySQL :
        {
            db = QSqlDatabase::addDatabase("QMYSQL", Constants::DB_ALARMES);
            db.setHostName(host);
            db.setDatabaseName(Constants::DB_ALARMES);
            db.setUserName(log);
            db.setPassword(pass);
              if (WarnDebugMessage){
                qWarning() << "Connecting Accountancy database" << host << Constants::DB_ALARMES << log << pass << port;
              }
            dbTest = (!db.isOpen()) && (!db.open());
            break;
        }
        case Driver_SQLite :
        {
            db = QSqlDatabase::addDatabase("QSQLITE", Constants::DB_ALARMES);
            db.setDatabaseName(settings()->userResourcesPath() + QDir::separator() + Constants::DB_ALARMES + ".db");
              if (WarnDebugMessage){
                qWarning() << "Connecting Accountancy database SQLite " + db.databaseName() +" "+ QString::number(__LINE__);
              }
            if(!db.open()){
                qWarning() << "database accountancy cannot open";
            }
            QStringList tables = db.tables();
            qDebug() << "tables "+QString::number(tables.size());
            dbTest = (tables.size() < 1);
            break;
        }
        case Driver_PostGreSQL :
            break;
    }

    if (dbTest) {
        if (!createDatabaseSchema(driverType)) {
            QMessageBox::warning(qApp->activeWindow(),
                                 tr("Fatal error"),
                                 tr("Unable to connect  database. Application will not work."),
                                 QMessageBox::Abort);
            qWarning() << "FATAL ERROR : Enable to create the  database";
            return false;
        }
        else {
            if (WarnDebugMessage)
                qWarning() << "Connected to Accountancy database"
                           << db.databaseName()
                           << __FILE__
                           << QString::number(__LINE__);
        }
        return false;
    }
    if(isDatabaseCorrupted(driverType,db)){
        QMessageBox::critical(0,trUtf8("Critical"),trUtf8("La base n'est pas installée")
               +QString(__FILE__)+"\n"+QString::number(__LINE__),
               QMessageBox::Ok);
        return false;
    }
    return true;
}

bool Connexion::isDatabaseCorrupted(const int driverType,QSqlDatabase &db)
{

    QString driverName = "";
    if(driverType == Driver_MySQL){
        driverName = MYSQL;
        }
    if(driverType == Driver_SQLite){
        driverName = SQLITE;
        }
    if(driverType == Driver_PostGreSQL){
        driverName = POSTGRESQL;
        }
    if(!db.isOpen()){
       qDebug() << "db is not opened " << __FILE__ << __LINE__;
    }
    qDebug() << __FILE__ << " driverName ="+driverName;
    qDebug() << __FILE__ << " database ="+db.connectionName();

    int tablesCount = Common::ICore::instance()->settings()->value(S_NBR_OF_TABLES).toInt();
   /* if(isAnIndependantProgram() || db.tables().contains("nameindex") ){
        qDebug() << "It is an independant program " << __FILE__ << __LINE__;
             tablesCount += 1;
    }*/
    QSqlTableModel model(this,db);
    model.setTable(QString(DB_ALARMES));
    int count = model.columnCount();
    qDebug() << __FILE__ << QString::number(__LINE__) << " count =" << QString::number(count);
    qDebug() << __FILE__ << QString::number(__LINE__) << " tableCount =" << QString::number(tablesCount);
    return count !=tablesCount;
}

/*bool Connexion::isAnIndependantProgram(){
    QString programName = Common::ICore::instance()->commandLine()->value(Common::CommandLine::CL_ProgramName).toString();
    if(!programName.isEmpty()){
        return false;
    }
    return true;
}*/

bool Connexion::createFirstSqlConnection() const
{
     qDebug() << "in createFirstSqlConnection" << __FILE__;
     if(!settings()->writeAllDefaults()) {
         return false;
     }
     mdp * databaseData = new mdp;
     if(databaseData->exec() == QDialog::Accepted) {
         settings()->setValue(Constants::S_DB_LOGIN,   databaseData->mdpLogin());
         settings()->setValue(Constants::S_DB_PASSWORD,databaseData->mdpPassword());
         settings()->setValue(Constants::S_DB_HOST,    databaseData->mdpHost());

     }
     QSqlDatabase db = QSqlDatabase :: addDatabase(Constants::MYSQL,Constants::DB_FIRST_CONNECTION);
     db.setHostName(settings()->value(S_DB_HOST).toString());
     db.setDatabaseName("mysql");
     db.setUserName(settings()->value(S_DB_LOGIN).toString());
     db.setPassword(settings()->value(S_DB_PASSWORD).toString());
     if(!db.open()) {
         qWarning() << "la base firstConnection ne peut être ouverte.";
     return false;
     }
      qDebug() << __FILE__ << " " << QString::number(__LINE__);
  return true;
}

bool Connexion::createDatabase(const int driver) const
{
    qDebug()<< "in createDatabase" << __FILE__;
    if (driver==Driver_SQLite)
        return true;

    if (!createFirstSqlConnection()) {//MYSQL
        QMessageBox::warning(qApp->activeWindow(),
                             tr("Fatal error"),
                             tr("An error occured during accountancy database creation.\nDo you have ")+Constants::MYSQL+""
                             ""+tr(" installed ?"),
                             QMessageBox::Abort);
    }
    QSqlDatabase dbFirst = QSqlDatabase::database(Constants::DB_FIRST_CONNECTION);
    QString reqForA = "CREATE DATABASE alarmes";
    QSqlQuery q(dbFirst);
    q.exec(reqForA);
    if (q.lastError().isValid() == true) {
        QMessageBox::warning(qApp->activeWindow(),
                             tr("Fatal error"),
                             tr("An error occured during accountancy database creation.\n")
                             +__FILE__+" "+QString::number(__LINE__),
                             QMessageBox::Abort);
        if (WarnDebugMessage)
            qWarning() << "SQL Error" << q.lastError().text() ;
        return false;
    }
    return true;
}



bool Connexion::createDatabaseSchema(const int driver)
{
    bool result = true;
    if ((driver!=Driver_SQLite) && (!createDatabase(driver))) {
        QMessageBox::critical(0, tr("Critical"), tr("Unable to create database."), QMessageBox::Ok);
        result = false;
    }
    QHash<QString, QString> name_sql;
//    name_sql.insert("Database creation", "CREATE DATABASE comptabilite");
    if (driver==Driver_MySQL) {
    name_sql.insert("Table alarmes",
                    "CREATE TABLE IF NOT EXISTS alarmes ("
                    "ID_Primkey bigint(20) UNSIGNED  NOT NULL  auto_increment ,"
                    "TextAlarme   longtext COLLATE utf8_unicode_ci NULL,"
                    "Alarm_Date	datetime  NULL,"
                    "Alarm_AlarmDate datetime  NULL,"
                    "Nom	varchar(50)   NULL,"
                    "Prenom	varchar(50)   NULL,"
                    "Alarm_IDDos	varchar(36)   NULL,"
                    "Alarm_valid	tinyint(1)  NULL,"
                    "Alarm_utilisateur	varchar(30)  NULL,"
                    "PRIMARY KEY(ID_Primkey));");
    /*if(isAnIndependantProgram()){
        name_sql.insert("Table nameindex",
                        "CREATE TABLE IF NOT EXISTS  nameindex ("
                        "id_index         int(6)                 unsigned                    NOT NULL auto_increment,"
                        "name             varchar(50)            COLLATE  utf8_unicode_ci    NULL,"
                        "surname          varchar(50)            COLLATE  utf8_unicode_ci    NULL,"
                        "guid             varchar(6)                                         NOT NULL,"
                        "PRIMARY KEY(id_index));");
    }*/
    }
    else if(driver==Driver_SQLite) {
    name_sql.insert("Table alarmes",
                    "CREATE TABLE IF NOT EXISTS	alarmes  ("
                    "ID_Primkey   INTEGER PRIMARY KEY,"
                    "TextAlarme   longtext   NULL,"
                    "Alarm_Date	datetime   NULL,"
                    "Alarm_AlarmDate	datetime   NULL,"
                    "Nom	varchar(50)   NULL,"
                    "Prenom	varchar(50)   NULL,"
                    "Alarm_IDDos	varchar(36)   NULL,"
                    "Alarm_valid	tinyint(1)  NULL,"
                    "Alarm_utilisateur	varchar(30)  NULL);");



   /* if(isAnIndependantProgram()){
        name_sql.insert("Table nameindex",
                   "CREATE TABLE IF NOT EXISTS  nameindex ("
                   "id_index         integer primary key,"
                   "name             varchar(50)     NULL,"
                   "surname          varchar(50)     NULL,"
                   "guid             varchar(6)      NOT NULL);");

    }*/

    }

    // Mass execute SQL queries
    QSqlDatabase db = QSqlDatabase::database(Constants::DB_ALARMES);
    if ((!db.isOpen()) && (!db.open())) {  
        if (WarnDebugMessage)
            qWarning() << __FILE__ << QString::number(__LINE__) << "Unable to create database, "
                                                                   "database can not be open.";
        result = false;
    }
    qDebug() << __FILE__ << QString::number(__LINE__) <<  "Hash Size "+QString::number(name_sql.size());
    QHashIterator<QString, QString> it(name_sql);
     while (it.hasNext()) {
         it.next();
         QSqlQuery q(db);
         QString req = it.value();
         if (driver==Driver_SQLite) {
             req = req.remove("COLLATE utf8_unicode_ci", Qt::CaseInsensitive).remove("UNSIGNED", Qt::CaseInsensitive);

         }
         q.exec(req);
         // Is there an error with this req ?
         if (q.lastError().isValid()) {
             QMessageBox::warning(qApp->activeWindow(),
                                  tr("Fatal error"),
                                  tr("An error occured during  database creation.\n"
                                     "Reference : %1\n"
                                     "Error : %2\n\n"
                                     "Application will not work.")
                                  .arg(it.key()).arg(q.lastError().text())+QString::number(__LINE__),
                                  QMessageBox::Abort);
             if (WarnDebugMessage)
                 qWarning() << __FILE__ << QString::number(__LINE__) << "SQL Error" << it.key() << q.lastError().text();
             result = false;
         }
     }
     //-------table paiements et remplissage des bases d'initialisation ----------------------------------
   int numberOfTables = Common::ICore::instance()->settings()->value(S_NBR_OF_TABLES).toInt();
  /* if(isAnIndependantProgram()){
       numberOfTables++;
   }*/
   QMessageBox mess;
               mess.setText(trUtf8("La base  a été installée "
                 "avec ")+QString::number(numberOfTables)
                 +trUtf8(" tables."));
               mess.setStandardButtons(QMessageBox::Close);
               mess.setDefaultButton(QMessageBox::Close);
               int r = mess.exec();
               qWarning() << __FILE__ << QString::number(__LINE__) << "r = "<< QString::number(r) ;
              
    return result;
}





